home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / dev / devSyslog.c < prev    next >
C/C++ Source or Header  |  1992-12-18  |  14KB  |  608 lines

  1. /* 
  2.  * devSyslog.c --
  3.  *
  4.  *    Device driver for processing internal kernel writes to the console.
  5.  *            
  6.  * Copyright 1986 Regents of the University of California
  7.  * All rights reserved.
  8.  */
  9.  
  10. #ifndef lint
  11. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/dev/devSyslog.c,v 9.9 92/08/03 18:04:49 mgbaker Exp $ SPRITE (Berkeley)";
  12. #endif not lint
  13.  
  14.  
  15. #include <sprite.h>
  16. #include <dev.h>
  17. #include <fs.h>
  18. #include <fsio.h>
  19. #include <fsioDevice.h>
  20. #include <sys.h>
  21. #include <machMon.h>
  22. #include <sig.h>
  23. #include <stdlib.h>
  24. #include <sync.h>
  25. #include <sched.h>
  26. #include <proc.h>
  27. #include <timer.h>
  28. #include <dbg.h>
  29. #include <list.h>
  30. #include <bstring.h>
  31.  
  32. /*
  33.  * Definition of mutual exclusion variable.
  34.  */
  35. static Sync_Semaphore    syslogMutex = Sync_SemInitStatic("Dev:syslogMutex");
  36. /*
  37.  * Monitored circular buffer of data written out by the kernel.
  38.  */
  39. #define    SYSLOG_BUF_SIZE    8192
  40. static    char    syslogBuffer[SYSLOG_BUF_SIZE];
  41. static    int    firstIndex = -1;
  42. static    int    lastIndex = -1;
  43.  
  44. static    Boolean syslogEnable = TRUE;
  45. static    Boolean    openForReading = FALSE;    /* TRUE if the device is open for
  46.                      * reading.  Only one process can
  47.                      * be reading syslog at a time. */
  48. static    Fs_NotifyToken notifyToken;    /* Used for Fs call-back to notify
  49.                      * waiting processes that the syslog
  50.                      * device is ready.*/
  51. static    Boolean       overflow = FALSE;
  52.  
  53.  
  54. /*
  55.  *----------------------------------------------------------------------
  56.  *
  57.  * Dev_SyslogOpen --
  58.  *
  59.  *    Open the system log device.
  60.  *
  61.  * Results:
  62.  *    SUCCESS        - the device was opened.
  63.  *    FAILURE        - some other reader is already reading the syslog.
  64.  *
  65.  * Side effects:
  66.  *    The system log is "opened" and static variables are initialized.
  67.  *
  68.  *----------------------------------------------------------------------
  69.  */
  70. /*ARGSUSED*/
  71. ReturnStatus
  72. Dev_SyslogOpen(devicePtr, useFlags, token, flagsPtr)
  73.     Fs_Device *devicePtr;    /* Specifies type and unit number. */
  74.     int useFlags;        /* Flags from the stream.  We only allow
  75.                  * a single reader at one time. */
  76.     Fs_NotifyToken token;    /* Used for Fs call-back to notify waiting
  77.                  * processes that the syslog device is ready.*/
  78.     int *flagsPtr;            /* OUT: Device IO flags */
  79. {
  80.     MASTER_LOCK(&syslogMutex);
  81.     Sync_SemRegister(&syslogMutex);
  82.     if (useFlags & FS_READ) {
  83.     if (openForReading) {
  84.         MASTER_UNLOCK(&syslogMutex);
  85.         return(FAILURE);
  86.     }
  87.     openForReading = TRUE;
  88.     }
  89.     notifyToken = token;
  90.     MASTER_UNLOCK(&syslogMutex);
  91.     return(SUCCESS);
  92. }
  93.  
  94. /*
  95.  *----------------------------------------------------------------------
  96.  *
  97.  * Dev_SyslogReopen --
  98.  *
  99.  *    Reopen the system log device.  This uses Dev_SyslogOpen to
  100.  *    do all the work.
  101.  *
  102.  * Results:
  103.  *    SUCCESS        - the device was opened.
  104.  *    FAILURE        - some other reader is already reading the syslog.
  105.  *
  106.  * Side effects:
  107.  *    See Dev_SyslogOpen.
  108.  *
  109.  *----------------------------------------------------------------------
  110.  */
  111. /*ARGSUSED*/
  112. ReturnStatus
  113. Dev_SyslogReopen(devicePtr, refs, writers, token, flagsPtr)
  114.     Fs_Device *devicePtr;    /* Specifies type and unit number. */
  115.     int refs;            /* Number of existing opens */
  116.     int writers;        /* Number of existing writers */
  117.     Fs_NotifyToken token;    /* Used for Fs call-back to notify waiting
  118.                  * processes that the console device is ready.*/
  119.     int *flagsPtr;            /* OUT: Device IO flags */
  120. {
  121.     int useFlags;
  122.  
  123.     /*
  124.      * Because there can only be a single reader of dev syslog,
  125.      * and it is most always a local process, we deny a reopen
  126.      * for reading.  Unfortuneatly we can't always tell exactly
  127.      * because 'refs' includes writers.  The whole usage state
  128.      * needs to be fixed to be 'readers', not 'refs'.
  129.      */
  130.     if (refs == writers) {
  131.     useFlags = FS_WRITE;
  132.     } else {
  133.     return(DEV_BUSY);
  134.     }
  135.     return( Dev_SyslogOpen(devicePtr, useFlags, token, (int *) NIL) );
  136. }
  137.  
  138.  
  139. /*
  140.  *----------------------------------------------------------------------
  141.  *
  142.  * Dev_SyslogRead --
  143.  *
  144.  *    Copy data out of the syslog buffer.
  145.  *
  146.  * Results:
  147.  *    FS_WOULD_BLOCK if no data available, otherwise SUCCESS.
  148.  *
  149.  * Side effects:
  150.  *    Data is removed from the syslog buffer.
  151.  *
  152.  *----------------------------------------------------------------------
  153.  */
  154. /*ARGSUSED*/
  155. ReturnStatus
  156. Dev_SyslogRead(devicePtr, readPtr, replyPtr)
  157.     Fs_Device    *devicePtr;
  158.     Fs_IOParam    *readPtr;    /* Read parameter block */
  159.     Fs_IOReply    *replyPtr;    /* Return length and signal */ 
  160. {
  161.     int        toRead;
  162.     int        bytesLeft;
  163.     Address    copyAddr;
  164.     Address    bufPtr = readPtr->buffer;
  165.  
  166.     bytesLeft = readPtr->length;
  167.  
  168.     MASTER_LOCK(&syslogMutex);
  169.     overflow = FALSE;
  170.     if (firstIndex == -1) {
  171.     replyPtr->length = 0;
  172.     MASTER_UNLOCK(&syslogMutex);
  173.     return(FS_WOULD_BLOCK);
  174.     }
  175.     if (firstIndex > lastIndex) {
  176.     toRead = SYSLOG_BUF_SIZE - firstIndex;
  177.     copyAddr = &syslogBuffer[firstIndex];
  178.     if (toRead <= bytesLeft) {
  179.         firstIndex = 0;
  180.     } else {
  181.         toRead = bytesLeft;
  182.         firstIndex += toRead;
  183.     }
  184.     bcopy(copyAddr, bufPtr,toRead);
  185.     bufPtr += toRead;
  186.     bytesLeft -= toRead;
  187.     }
  188.     if (bytesLeft > 0) {
  189.     toRead = lastIndex - firstIndex + 1;
  190.     copyAddr = &syslogBuffer[firstIndex];
  191.     if (toRead <= bytesLeft) {
  192.         firstIndex = -1;
  193.         lastIndex = -1;
  194.     } else {
  195.         toRead = bytesLeft;
  196.         firstIndex += toRead;
  197.     }
  198.     bcopy(copyAddr, bufPtr,toRead);
  199.     bytesLeft -= toRead;
  200.     }
  201.     MASTER_UNLOCK(&syslogMutex);
  202.     replyPtr->length = readPtr->length - bytesLeft;
  203.     return(SUCCESS);
  204. }
  205.  
  206.  
  207. /*
  208.  *----------------------------------------------------------------------
  209.  *
  210.  * Dev_SyslogWrite --
  211.  *
  212.  *    Write characters to the system log.  If the device isn't open
  213.  *    then Mach_MonPutChar is used to output directly to the screen.  
  214.  *    Otherwise data is output to a buffer that is emptied by
  215.  *    reading the syslog device.
  216.  *
  217.  * Results:
  218.  *    SUCCESS.
  219.  *
  220.  * Side effects:
  221.  *    Data is written to the console or to the buffer.
  222.  *
  223.  *----------------------------------------------------------------------
  224.  */
  225. /*ARGSUSED*/
  226. ReturnStatus
  227. Dev_SyslogWrite(devicePtr, writePtr, replyPtr)
  228.     Fs_Device     *devicePtr;        /* Ignored. */
  229.     Fs_IOParam    *writePtr;    /* Standard write parameter block */
  230.     Fs_IOReply    *replyPtr;    /* Return length and signal */
  231. {
  232.     int    i;
  233.     int    toWrite;
  234.     int origSize = writePtr->length;
  235.     Address bufPtr = writePtr->buffer;
  236.  
  237.  
  238.     if (!syslogEnable) {
  239.     replyPtr->length = writePtr->length;
  240.     return(SUCCESS);
  241.     }
  242.  
  243.     if (!dbg_UsingSyslog) {
  244.     if (!openForReading) {
  245.         for (i = 0; i < writePtr->length; i++, bufPtr++) {
  246.         if (!sys_DontPrint) {
  247.             Mach_MonPutChar(*bufPtr);
  248.         }
  249.         }
  250.         replyPtr->length = writePtr->length;
  251.         return(SUCCESS);
  252.     }
  253.     MASTER_LOCK(&syslogMutex);
  254.     }
  255.  
  256.     if (firstIndex != -1 && firstIndex <= lastIndex) {
  257.     /*
  258.      * Fill up until the end of the buffer or until run out of
  259.      * bytes, whichever comes first.
  260.      */
  261.     toWrite = SYSLOG_BUF_SIZE - (lastIndex + 1);
  262.     if (toWrite > writePtr->length) {
  263.         toWrite = writePtr->length;
  264.     }
  265.     bcopy(bufPtr, &syslogBuffer[lastIndex + 1], toWrite);
  266.     writePtr->length -= toWrite;
  267.     bufPtr += toWrite;
  268.     lastIndex += toWrite;
  269.     }
  270.     if (writePtr->length > 0) {
  271.     int    nextIndex;
  272.  
  273.     nextIndex = lastIndex + 1;
  274.     if (nextIndex == SYSLOG_BUF_SIZE) {
  275.         nextIndex = 0;
  276.     }
  277.     if (nextIndex == firstIndex) {
  278.         /*
  279.          * Buffer overflow
  280.          */
  281.         if (!overflow) {
  282.         Mach_MonPrintf("Dev_SyslogWrite: Buffer overflow ...\n");
  283.         overflow = TRUE;
  284.         }
  285.         for (i = 0; i < writePtr->length; i++, bufPtr++) {
  286.         if (!sys_DontPrint) {
  287.             Mach_MonPutChar(*bufPtr);
  288.         }
  289.         }
  290.         /*
  291.          * Make sure we return that the entire amount was written.
  292.          */
  293.         writePtr->length = 0;
  294.     } else {
  295.         if (firstIndex == -1) {
  296.         toWrite = SYSLOG_BUF_SIZE;
  297.         firstIndex = 0;
  298.         } else {
  299.         toWrite = firstIndex - nextIndex;
  300.         }
  301.         if (toWrite > writePtr->length) {
  302.         toWrite = writePtr->length;
  303.         }
  304.         bcopy(bufPtr, syslogBuffer, toWrite);
  305.         lastIndex = nextIndex + toWrite - 1;
  306.         writePtr->length -= toWrite;
  307.     }
  308.     }
  309.  
  310.     if (!dbg_UsingSyslog) {
  311.     Fsio_DevNotifyReader(notifyToken);
  312.     MASTER_UNLOCK(&syslogMutex);
  313.     }
  314.     replyPtr->length = origSize - writePtr->length;
  315.  
  316.     return(SUCCESS);
  317. }
  318.  
  319.  
  320.  
  321. /*
  322.  *----------------------------------------------------------------------
  323.  *
  324.  * Dev_SyslogPutChar --
  325.  *
  326.  *    Write a single character to the system log.
  327.  *
  328.  * Results:
  329.  *    None.
  330.  *
  331.  * Side effects:
  332.  *    None.
  333.  *
  334.  *----------------------------------------------------------------------
  335.  */
  336. /*ARGSUSED*/
  337. void
  338. Dev_SyslogPutChar(ch)
  339.     char    ch;
  340. {
  341.     Fs_IOParam io;
  342.     Fs_IOReply reply;
  343.  
  344.     io.buffer = &ch;
  345.     io.length = 1;
  346.     io.offset = 0;
  347.     io.flags = 0;
  348.     reply.signal = 0;
  349.  
  350.     (void) Dev_SyslogWrite((Fs_Device *) NIL, &io, &reply);
  351. }
  352.  
  353.  
  354. /*
  355.  *----------------------------------------------------------------------
  356.  *
  357.  * Dev_SyslogClose --
  358.  *
  359.  *    Close the system log and flush any remaining output.
  360.  *
  361.  * Results:
  362.  *    SUCCESS        - always returned.
  363.  *
  364.  * Side effects:
  365.  *    The console is "closed".
  366.  *
  367.  *----------------------------------------------------------------------
  368.  */
  369. /* ARGSUSED */
  370. ReturnStatus
  371. Dev_SyslogClose(devicePtr, useFlags, openCount, writerCount)
  372.     Fs_Device    *devicePtr;
  373.     int        useFlags;
  374.     int        openCount;
  375.     int        writerCount;
  376. {
  377.     int    i;
  378.  
  379.     MASTER_LOCK(&syslogMutex);
  380.     if (useFlags & FS_READ) {
  381.     openForReading = FALSE;
  382.     if (firstIndex != -1) {
  383.         if (firstIndex <= lastIndex) {
  384.         for (i = firstIndex; i <= lastIndex; i++) {
  385.             if (!sys_DontPrint) {
  386.             Mach_MonPutChar(syslogBuffer[i]);
  387.             }
  388.         }
  389.         } else {
  390.         for (i = firstIndex; i < SYSLOG_BUF_SIZE; i++) {
  391.             if (!sys_DontPrint) {
  392.             Mach_MonPutChar(syslogBuffer[i]);
  393.             }
  394.         }
  395.         for (i = 0; i <= lastIndex; i++)  {
  396.             if (!sys_DontPrint) {
  397.             Mach_MonPutChar(syslogBuffer[i]);
  398.             }
  399.         }
  400.         }
  401.         firstIndex = -1;
  402.         lastIndex = -1;
  403.     }
  404.     }
  405.     MASTER_UNLOCK(&syslogMutex);
  406.     return(SUCCESS);
  407. }
  408.  
  409.  
  410. /*
  411.  *----------------------------------------------------------------------
  412.  *
  413.  * Dev_SyslogIOControl --
  414.  *
  415.  *    Perform device-specific functions with the console.
  416.  *
  417.  * Results:
  418.  *    GEN_NOT_IMPLEMENTED if io control not supported.
  419.  *
  420.  * Side effects:
  421.  *    None.
  422.  *
  423.  *----------------------------------------------------------------------
  424.  */
  425. /* ARGSUSED */
  426. ReturnStatus
  427. Dev_SyslogIOControl(devicePtr, ioctlPtr, replyPtr)
  428.     Fs_Device            *devicePtr;
  429.     Fs_IOCParam        *ioctlPtr;
  430.     Fs_IOReply        *replyPtr;
  431. {
  432.     ReturnStatus    status = SUCCESS;
  433.  
  434.     MASTER_LOCK(&syslogMutex);
  435.     switch (ioctlPtr->command) {
  436.     case    IOC_REPOSITION:
  437.         /*
  438.          * Reposition doesn't matter
  439.          */
  440.         break;
  441.     case    IOC_GET_FLAGS:
  442.     case    IOC_SET_FLAGS:
  443.     case    IOC_SET_BITS:
  444.     case    IOC_CLEAR_BITS:
  445.         /*
  446.          * No syslog specific bits are set this way.
  447.          */
  448.         break;
  449. #ifdef notdef
  450.     case    IOC_TRUNCATE:
  451.         firstIndex = -1;
  452.         lastIndex = - 1;
  453.         break;
  454. #endif
  455.  
  456.     default:
  457.         status = GEN_NOT_IMPLEMENTED;
  458.     }
  459.     MASTER_UNLOCK(&syslogMutex);
  460.     return(status);
  461. }
  462.  
  463.  
  464. /*
  465.  *----------------------------------------------------------------------
  466.  *
  467.  * Dev_SyslogSelect --
  468.  *
  469.  *    Perform device-specific select functions with the console.
  470.  *
  471.  * Results:
  472.  *    SUCCESS    
  473.  *
  474.  * Side effects:
  475.  *    None.
  476.  *
  477.  *----------------------------------------------------------------------
  478.  */
  479. /*ARGSUSED*/
  480. ReturnStatus
  481. Dev_SyslogSelect(devicePtr, readPtr, writePtr, exceptPtr)
  482.     Fs_Device            *devicePtr;
  483.     int            *readPtr;
  484.     int            *writePtr;
  485.     int            *exceptPtr;
  486. {
  487.     MASTER_LOCK(&syslogMutex);
  488.     if (*readPtr) {
  489.     if (lastIndex == -1) {
  490.         *readPtr = 0;
  491.     }
  492.     }
  493.     if (*writePtr) {
  494.     if (firstIndex == lastIndex + 1) {
  495.         *writePtr = 0;
  496.     }
  497.     }
  498.     *exceptPtr = 0;
  499.     MASTER_UNLOCK(&syslogMutex);
  500.     return(SUCCESS);
  501. }
  502.  
  503. static    Boolean    savedOpenForReading;
  504. static    int    syslogDebugCount = 0;
  505.  
  506.  
  507. /*
  508.  *----------------------------------------------------------------------
  509.  *
  510.  * Dev_SyslogDebug --
  511.  *
  512.  *    Start or stop redirecting output to the log buffer.  This is intended
  513.  *    to be called by Dbg_Main when entering and leaving the debugger and
  514.  *    by panic() so that debugger output will go on the
  515.  *    console since no process can run to flush the buffer.
  516.  *
  517.  * Results:
  518.  *    None.
  519.  *
  520.  * Side effects:
  521.  *    Redirecting output to the log buffer is turned off or on.
  522.  *
  523.  *----------------------------------------------------------------------
  524.  */
  525. void
  526. Dev_SyslogDebug(stopLog)
  527.     Boolean    stopLog;    /* TRUE => stop storing log output into the
  528.                  *         buffer. */
  529. {
  530.     if (stopLog) {
  531.     if (syslogDebugCount == 0) {
  532.         savedOpenForReading = openForReading;
  533.         Dev_SyslogClose((Fs_Device *) NIL, FS_READ, 0, 0);
  534.     }
  535.         syslogDebugCount++;
  536.     } else {
  537.     syslogDebugCount--;
  538.     if (syslogDebugCount == 0) {
  539.         openForReading = savedOpenForReading;
  540.     }
  541.     }
  542. }
  543.  
  544.  
  545.  
  546. /*
  547.  *----------------------------------------------------------------------
  548.  *
  549.  * Dev_SyslogReturnBuffer --
  550.  *
  551.  *    Return the data in the syslog buffer to the caller.  Intended to be
  552.  *    called by the debugger.
  553.  *
  554.  * Results:
  555.  *    Pointer to buffer and the first and last indices.
  556.  *
  557.  * Side effects:
  558.  *    None.
  559.  *
  560.  *----------------------------------------------------------------------
  561.  */
  562. void
  563. Dev_SyslogReturnBuffer(bufPtrPtr, firstIndexPtrPtr, lastIndexPtrPtr, bufSizePtr)
  564.     char    **bufPtrPtr;
  565.     int        **firstIndexPtrPtr;
  566.     int        **lastIndexPtrPtr;
  567.     int        *bufSizePtr;
  568. {
  569.     *bufPtrPtr = syslogBuffer;
  570.     *firstIndexPtrPtr = &firstIndex;
  571.     *lastIndexPtrPtr = &lastIndex;
  572.     *bufSizePtr = SYSLOG_BUF_SIZE;
  573. }
  574.  
  575.  
  576. /*
  577.  *----------------------------------------------------------------------
  578.  *
  579.  * Dev_SyslogDisable --
  580.  *
  581.  *    Toggles syslog on/off.
  582.  *
  583.  * Results:
  584.  *    None.
  585.  *
  586.  * Side effects:
  587.  *    None.
  588.  *
  589.  *----------------------------------------------------------------------
  590.  */
  591. /* ARGSUSED */
  592. void
  593. Dev_SyslogDisable(dummy)
  594.     ClientData dummy;
  595. {
  596.     if (syslogEnable) {
  597.     MASTER_LOCK(&syslogMutex);
  598.     firstIndex = -1;
  599.     lastIndex = - 1;
  600.     syslogEnable = FALSE;
  601.     MASTER_UNLOCK(&syslogMutex);
  602.     } else {
  603.     MASTER_LOCK(&syslogMutex);
  604.     syslogEnable = TRUE;
  605.     MASTER_UNLOCK(&syslogMutex);
  606.     }
  607. }
  608.